<template>
  <div>
    <CategorySelector :isShowtime="!isShowAttrList"></CategorySelector>
    <el-card style="margin-top: 20px">
      <div v-if="isShowAttrList">
        <!-- 添加按钮 -->
        <el-button type="primary" :icon="Plus" :disabled="!categoryStore.category3Id" style="margin-bottom: 10px" @click="isShowAttrListOr">添加属性</el-button>

        <el-table border :data="attrList">
          <el-table-column label="序号" width="80px" type="index" align="center"> </el-table-column>
          <el-table-column label="属性名" prop="attrName" width="200px"> </el-table-column>
          <!-- <el-table-column label="属性值列表" prop="attrName.attrValueList.valueName"> </el-table-column>
        由于这一行是渲染的几个tag标签,所以不能用prop来做列渲染 -->
          <el-table-column label="属性值列表">
            <template v-slot="{ row }">
              <!-- row拿到的是当前遍历的数组的当前值 -->
              <el-tag v-for="attrValue in row.attrValueList" :id="attrValue.id" class="ml-2" type="success" style="margin-right: 6px">{{ attrValue.valueName }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="200px">
            <template #default="{ row }">
              <el-button title="修改" size="small" type="warning" :icon="Edit" @click="editAttrData(row)" />
              <!-- <el-button title="修改" size="small" type="warning" :icon="Edit" /> -->
              <el-popconfirm title="Are you sure to Delete this?" :icon="InfoFilled" icon-color="red" @confirm="delAttrOne(row.id)" @cancel="cancel">
                <template #reference>
                  <el-button title="删除" size="small" type="danger" :icon="Delete" />
                </template>
              </el-popconfirm>
              <!-- <el-button title="删除" size="small" type="danger" :icon="Delete" /> -->
            </template>
          </el-table-column>
        </el-table>
      </div>

      <!-- 与查看属性列表是互斥的,这个是进行修改的界面 -->
      <div v-else>
        <el-form>
          <el-form-item label="属性名">
            <el-input placeholder="请输入属性名" v-model="attrInfo.attrName"></el-input>
          </el-form-item>
          <el-button style="margin-bottom: 10px" :disabled="!attrInfo.attrName" @click="AddAttrsValue" type="primary" :icon="Plus">添加属性值</el-button>
        </el-form>
        <el-table border :data="attrInfo.attrValueList">
          <el-table-column label="序号" width="100px" type="index" align="center"></el-table-column>
          <el-table-column label="属性值名称">
            <!-- 属性值是动态的,我们可以用一个插槽来做 -->
            <template v-slot="{ row, $index }">
              <!-- 这两个标签是互斥的用if-else来   row就是这一行的被代理的对象-->
              <el-input v-if="row.isShowInput" v-model="row.valueName" ref="inputRef" @blur="deleteCurrentRow(row, $index)"></el-input>
              <span v-else style="display: inline-block; width: 100%" @dblclick="showInput(row)">{{ row.valueName }}</span>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template v-slot="{ row }">
              <el-popconfirm title="Are you sure to Delete this?" :icon="InfoFilled" icon-color="red" @confirm="delThisData($index)" @cancel="cancel">
                <template #reference>
                  <el-button title="删除" size="small" type="danger" :icon="Delete" />
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <div style="margin-top: 30px">
          <el-button type="primary" @click="saveAndAddListData" :disabled="!attrInfo.attrValueList.length">真的要添加了</el-button>
          <el-button type="default" @click="isShowAttrList = true">不</el-button>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script lang="ts">
import CategorySelector from "@/components/CategorySelector/index.vue"
export default {
  name: "Attr",
  components: {
    CategorySelector,
  },
}
</script>

<script lang="ts" setup>
//引入图标样式
import { Plus, Edit, Delete, InfoFilled } from "@element-plus/icons-vue"
// 引入小菠萝里的数据
import { useCategoryListStore } from "@/stores/categoryList"
// 引入接口,发送一次请求
import { reqDelAttrListData, reqGetAttrListDataByCategory3Id, reqAddAttrInfoData } from "@/api/product/attr"
import { reactive, ref, watch, nextTick } from "vue"
import type { AttrInfoModel, AttrListModel, AttrValueInfoModel } from "@/api/product/model/attr"

const isShowAttrList = ref<boolean>(true) // 默认是添加界面

// 创建小菠萝实例 获取store
const categoryStore = useCategoryListStore()

// 定义一个数组来存储属性列表数据
const attrList = ref<AttrListModel>([])

// 定义一个响应式对象来储存待添加的数据
const attrInfo = reactive<AttrInfoModel>({
  attrName: "", // 要存储的属性名
  attrValueList: [], // 存储属性的数组
  categoryLevel: 3, // 等级
  categoryId: -1, // id值
})

// 定义一个变量 为对应输入框 以便用于获取输入框对象
// <HTMLInputElement>代表是元素
const inputRef = ref<HTMLInputElement>()

// 当点击第三个导航时,获取table数据,这个函数的执行时机就是,侦听到3级id的值不为undefined时,立刻发送请求
const getAttrListData = async () => {
  const result = await reqGetAttrListDataByCategory3Id({
    category1Id: categoryStore.category1Id as number,
    category2Id: categoryStore.category2Id as number,
    category3Id: categoryStore.category3Id as number,
  })
  // console.log("rr", result)
  // 获取到之后存入组件中已经创建好的attrList中,注意,一定要用ref包裹,形成响应式
  attrList.value = result // 使用了ref后,如果要操作值,需要在后面加一个.value
}
// 删除属性
const delAttrOne = async (id: number) => {
  // console.log(raw.id)
  await reqDelAttrListData(id)
  // 重新发送请求
  getAttrListData()
}
// 返回
const cancel = () => {
  console.log(123)
}
// 添加属性值
const AddAttrsValue = () => {
  // 这里的属性都要根据服务器响应需要的来进行收集数据,以便用户添加完成后,发送服务器,真正的添加
  attrInfo.attrValueList.push({
    // 这里对属性值的数据绑定
    valueName: "",
    isShowInput: true, // 是不是显示输入框 或是显示span标签
  })

  // 注意等页面中的内容渲染完毕之后，才来执行里面的业务逻辑
  nextTick(() => {
    inputRef.value?.focus()
  })
  // inputRef.value?.focus()// 如果不写nextTick,那么执行时机不对,每次获取的都是上次的焦点
}
// 失去焦点判断值是否为空,为空删除
const deleteCurrentRow = (row: AttrValueInfoModel, index: number) => {
  if (!row.valueName) {
    // 如果没有值，删除当前的行
    // 使用splice切割数据,根据当前索引,删除当前索引的数据
    attrInfo.attrValueList.splice(index, 1)
    return
  }
  // 如果有数据,那么将input隐藏,展示span
  row.isShowInput = false
}

// 双击span标签,展示input
const showInput = (row: AttrValueInfoModel) => {
  // 展示input框
  row.isShowInput = true
  // 将input自动获取焦点
  // 注意等页面中的内容渲染完毕之后，才来执行里面的业务逻辑
  nextTick(() => {
    inputRef.value?.focus()
  })
}

// 点击删除数据
const delThisData = (index: number) => {
  // 由于数据还未添加到服务器,所以直接在数组中删除即可
  attrInfo.attrValueList.splice(index, 1)
}

// 点击添加按钮清空之前的值
const isShowAttrListOr = () => {
  console.log(123)
  isShowAttrList.value = false
  // 清空添加属性中原先的数据

  // 由于添加修改都是一个接口，所以我们要真的添加之前，需要将修改时产生的id删除
  delete attrInfo.id
  attrInfo.attrName = ""
  attrInfo.attrValueList = []
}

// 真的添加数据l
const saveAndAddListData = async () => {
  // 注意:发送请求一定要根据服务器响应来的格式发送,不然就会出现请求成功但是没有成功达到预期效果的情况
  attrInfo.categoryId = categoryStore.category3Id
  // 这里在设置ts类型时, 会一直警告, 原因是这个值有可能为undefined, 但是我们设置的是number, 所以我们需要去ts中添加一个联合类型
  await reqAddAttrInfoData(attrInfo)
  // 跳转到列表页
  isShowAttrList.value = true
  // 重新发送请求
  getAttrListData()
}

// 编辑列表属性
const editAttrData = (row: AttrValueInfoModel) => {
  // attrInfo = row // 不能这样直接赋值
  // 使用对象的方法
  // 这样刚好将row当前属性的对应值,一一对应到属性页中的值上
  Object.assign(attrInfo, row)
  // 注意:由于修改时,会将id也发送到属性页中,如果我们不及时删除,那么在后面我们添加属性的操作,就会被认定为是更新,无论如何添加,都是修改的上次修改的那一项.

  // 跳转到属性页进行编辑
  isShowAttrList.value = false
}

// 监视三级导航Id
watch(
  // 监听的值一定是以箭头函数的值来返回的,换句话说,侦听属性的值一定是以函数的返回值的形式来的
  function () {
    return categoryStore.category3Id
  },
  category3Id => {
    // console.log("cca", category3Id)
    // 一旦获取到三级id,立刻发送请求获取table表格数据

    // 这里会用一种情况,当切换其他页面在切换回来的时候,此时还有3id,但是页面的table不渲染了
    // 还一种情况,当用户直接切换1id时,页面会报错
    // 统一解决
    // 首先判断是否有3id,有就发请求获取table表格,没有就返回,这样解决页面直接切换1id时的报错问题
    if (!category3Id) {
      // 这时发现页面不报错.但是table表格还有数据,所以还要清空table
      attrList.value = []
      // console.log(1)
      return
    }
    getAttrListData()
  },
  // 解决切换无法重新获取数据的问题 --->开启深度监视
  { immediate: true }
)
</script>
<style scoped></style>
